﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using PClusterModel.Cluster;

namespace MicroarrayDataPresentation
{
    internal class Report
    {
        private Dictionary<ClusterSize, int> clustersFound = new Dictionary<ClusterSize, int>();
        private Stopwatch subProcesStopwatch;
        private Stopwatch fullProcessStopWatch;
        private TimeSpan totalTime;
        private TimeSpan timeForCalculatingMDS;
        private TimeSpan timeForPrunning;
        private TimeSpan timeForClustering;
        private int totalNumberOfObjects;
        private int numberOfClusters;
        private int minNumberOfConditions;
        private int minNumberOfObjects;
        private decimal trashold;

        public int MinNumberOfConditions
        {
            get { return minNumberOfConditions; }
        }

        public int MinNumberOfObjects
        {
            get { return minNumberOfObjects; }
        }

        public decimal Trashold
        {
            get { return trashold; }
        }

        public TimeSpan TotalTime
        {
            get { return totalTime; }
        }

        public TimeSpan TimeForCalculatingMDS
        {
            get { return timeForCalculatingMDS; }
        }

        public TimeSpan TimeForPrunning
        {
            get { return timeForPrunning; }
        }

        public TimeSpan TimeForClustering
        {
            get { return timeForClustering; }
        }

        public Dictionary<ClusterSize, int> ClustersFound
        {
            get { return clustersFound; }
        }

        public int TotalNumberOfObjects
        {
            get { return totalNumberOfObjects; }
        }

        public int NumberOfClusters
        {
            get { return numberOfClusters; }
        }

        public Report(PClusterizer clusterizer)
        {
            this.subProcesStopwatch = new Stopwatch();
            this.fullProcessStopWatch = new Stopwatch();

            clusterizer.ClusteringStarting += new EventHandler(clusterizer_ClusteringStarting);
            clusterizer.MdsCalculationFinished += new EventHandler(clusterizer_MdsCalculationFinished);
            clusterizer.PrunningFinished += new EventHandler(clusterizer_PrunningFinished);
            clusterizer.ClusteringFinished += new PClusterizer.ClusteringFinishedEventHandler(clusterizer_ClusteringFinished);
            this.totalNumberOfObjects = clusterizer.DataSet.NumberOfDataObjects;
            this.minNumberOfConditions = clusterizer.MinNumberOfConditions;
            this.minNumberOfObjects= clusterizer.MinNumberOfObjects;
            this.trashold = clusterizer.Trashold;
        }

        void clusterizer_ClusteringFinished(object sender, ClusteringFinishedEventArgs e)
        {
            this.fullProcessStopWatch.Stop();
            this.subProcesStopwatch.Stop();
            this.timeForClustering = this.subProcesStopwatch.Elapsed;
            this.totalTime = this.fullProcessStopWatch.Elapsed;
            this.PopulateClustersFoundDictionary(e.Clusters);
        }

        private void PopulateClustersFoundDictionary(IList<IMicroarrayCluster> clusters)
        {
            if (clusters == null || clusters.Count == 0)
            {
                return;
            }
            this.numberOfClusters = clusters.Count;

            ClusterSize tempSize;
            foreach (IMicroarrayCluster cluster in clusters)
            {
                tempSize = new ClusterSize(cluster.NumberOfObjects, cluster.NumberOfConditions);
                if (this.clustersFound.ContainsKey(tempSize))
                {
                    this.clustersFound[tempSize]++;
                }
                else
                {
                    this.clustersFound.Add(tempSize, 1);
                }
            }
            
        }

        private void clusterizer_PrunningFinished(object sender, EventArgs e)
        {
            this.subProcesStopwatch.Stop();
            this.timeForPrunning = this.subProcesStopwatch.Elapsed;
            this.subProcesStopwatch.Restart();
        }

        private void clusterizer_MdsCalculationFinished(object sender, EventArgs e)
        {
            this.subProcesStopwatch.Stop();
            this.timeForCalculatingMDS = this.subProcesStopwatch.Elapsed;
            this.subProcesStopwatch.Restart();
        }

        private void clusterizer_ClusteringStarting(object sender, EventArgs e)
        {
            this.fullProcessStopWatch.Start();
            this.subProcesStopwatch.Start();
        }
    }

    internal struct ClusterSize
    {
        private int numberOfObjects;
        private int numberOfConditions;

        public ClusterSize(int numberOfObjects, int numberOfColumns)
        {
            this.numberOfObjects = numberOfObjects;
            this.numberOfConditions = numberOfColumns;
        }

        public int NumberOfObjects
        {
            get { return numberOfObjects; }
        }

        public int NumberOfConditions
        {
            get { return numberOfConditions; }
        }

        public override string ToString()
        {
            return string.Format("{0} x {1}", numberOfObjects, numberOfConditions);
        }

        public override int GetHashCode()
        {
            return this.ToString().GetHashCode();
        }
    }
}
